package fiuba.algo3.mundo;

import java.util.List;

import fiuba.algo3.GeneradorAleatorio;
import fiuba.algo3.mundo.NodoMundo;
import fiuba.algo3.motor.MotorXML;
import fiuba.algo3.persistencia.ConstructorNodoMundo;
import fiuba.algo3.persistencia.ConstructorPais;

public class Mundo
{
	private NodoMundo listaNodos[];
	private Pais listaPaises[];

	public Mundo()
	{
		this.inicializarListaPaises();
		this.inicializarListaNodos();
	}

	private void inicializarListaNodos()
	{
		String nombreArchivo = "baseDeDatos/nodoMundo.xml";

		this.listaNodos = ConstructorNodoMundo.construir(MotorXML.obtenerListadoXML(nombreArchivo));
	}

	private void inicializarListaPaises()
	{
		String nombreArchivo = "baseDeDatos/paises.xml";

		this.listaPaises = ConstructorPais.construir(MotorXML.obtenerListadoXML(nombreArchivo));

		int i;
		for (i = 0; i < listaPaises.length; i++){
			listaPaises[i].asignarLugaresSinInformacion();
		}

		this.cambiarOrdenPaises();
	}

	private void cambiarOrdenPaises() {
		int cantidadPaises = this.listaPaises.length;
		int i;
		List<Integer> indicesAleatorios = GeneradorAleatorio.generarNValoresAleatorios(cantidadPaises, cantidadPaises);
		Pais listaAux[] = new Pais[cantidadPaises];
		
		for (i=0; i<cantidadPaises; i++){
			listaAux[i] = listaPaises[indicesAleatorios.get(i)];
		}
		listaPaises = listaAux;
	}

	public NodoMundo[] obtenerMundoGrafo()
	{
		return this.listaNodos;
	}

	public Pais[] obtenerSecuenciaPaisesConectados(int cantidadPaises)
	{
		Pais listaPaises2[] = new Pais[cantidadPaises];

		System.arraycopy(this.listaPaises, 0, listaPaises2, 0, cantidadPaises);

		return listaPaises2;
	}

	public int obtenerIndicePais(String nombre)
	{
		for (int i = 0; i < listaPaises.length; i++)
		{
			if (listaPaises[i].obtenerNombre().equals(nombre))
				return i;
		}
		return -1;
	}

	public int obtenerIndiceNodo(int nodo)
	{
		return nodo;
	}

	public Pais obtenerPais(String nombre)
	{
		int indice = obtenerIndicePais(nombre);
		
		if (indice == -1)
			return null;
		
		return listaPaises[indice];
	}

	public Pais[] obtenerPaisesConectados(Pais pais)
	{
		int indice = obtenerIndicePais(pais.obtenerNombre());
		NodoMundo nodoActual = listaNodos[indice];

		int conexiones[] = nodoActual.obtenerConexiones();

		Pais listaConexiones[] = new Pais[conexiones.length];

		int j = 0;
		for (int i : conexiones)
			{
				listaConexiones[j] = listaPaises[i];
				j++;
			}

		return listaConexiones;
	}

	private NodoMundo buscarNodo(Pais pais)
	{
		for (int i = 0; i < listaPaises.length; i++)
		{
			if (listaPaises[i].esElMismoQue(pais))
			{
				return listaNodos[i];
			}
		}

		return null;
	}

	private boolean paisPertenceAlMundo(Pais pais)
	{
		return (buscarNodo(pais) != null);
	}

	private int obtenerCantidadNodos()
	{
		return listaNodos.length;
	}

	public void verificarExistenciaDePais(Pais pDestino)
	{
		if (!this.paisPertenceAlMundo(pDestino))
			throw new PaisNoPerteneceAlMundoExcepcion();
	}

	public void verificarConexionEntre(Pais pOrigen, Pais pDestino)
	{
		boolean salida = false;
		Pais paisesConectados[] = this.obtenerPaisesConectados(pOrigen);

		for (Pais paisesConectado : paisesConectados)
		{
			if (paisesConectado.esElMismoQue(pDestino))
				salida = true;
		}
		if (salida == false)
			throw new PaisesNoConectadosExcepcion();
	}
}
